using System;

namespace RapidHDL
{
	/// <summary>
	/// Summary description for Structure.
	/// </summary>
	public class Structure
	{
		public SharedDataCoordinator ComponentSharedDataCoordinator;
		public TruthTableCoordinator TruthTableCoordinator;
		public RapidHardware RapidHardware;
		public TopLevelComponent TopLevelComponent;

		private int iNextSourcePathId;

		private System.Collections.Hashtable oTestedComponents;

		public Structure(RapidHardware poRapidHardware)
		{
			RapidHardware = poRapidHardware;
			TruthTableCoordinator = new TruthTableCoordinator();
			TopLevelComponent = new TopLevelComponent(poRapidHardware);
			ComponentSharedDataCoordinator = new SharedDataCoordinator();
			iNextSourcePathId = 0;
		}

		public bool GenerateStructure()
		{
			TopLevelComponent.BaseGenerateStructure();
			if (!TopLevelComponent.SortStructure())
				return false;
			if (!TopLevelComponent.ValidateWellFormedComponent())
				return false;
			return true;
		}

		public void TestComponent(string psTestName, Component poComponent, string psComponentNameHirarchy)
		{
			RapidHardware oRapidHardware = new RapidHardware();

			string sTestResult;
			string sType;
			string sComponentNameHirarchy;

			oRapidHardware.InternalLog.EnableDisplayToConsole = true;
			oRapidHardware.InternalLog.DisplayLogs.Add(LogType.SimulationTrace);

			sType = poComponent.GetType().ToString();
			if (oTestedComponents.ContainsKey(sType))
				return;


			sComponentNameHirarchy = psComponentNameHirarchy + "." + poComponent.Name;
			
			oRapidHardware.InternalLog.Log(LogType.SimulationTrace, "");
			oRapidHardware.InternalLog.Log(LogType.SimulationTrace,"***** Starting Test of " + sType + " ********");

			sTestResult = poComponent.BaseTestComponent(oRapidHardware,psTestName);

			oRapidHardware.InternalLog.Log(LogType.SimulationTrace,"====== Finished Test of " + sType + " ========");
			oRapidHardware.InternalLog.Log(LogType.SimulationTrace,"");


			if (sTestResult != "")
				System.Diagnostics.Debug.Fail("Component of type '" + sType + "' failed test '" + psTestName + "' and returned '" + sTestResult + "'.  {" + sComponentNameHirarchy + "}");

			foreach(Component oComponent in poComponent.Components.Values)
			{
				TestComponent(psTestName,oComponent,sComponentNameHirarchy);
			}
		}

		public void TestAll(string psTestName)
		{
			string sComponentNameHirarchy = "TopLevelComponent";
			System.Diagnostics.Debug.WriteLine("********** Starting TestAll " + psTestName + "  **************");
			oTestedComponents = new System.Collections.Hashtable();
			
			foreach(Component oComponent in TopLevelComponent.Components.Values)
			{
				TestComponent(psTestName,oComponent,sComponentNameHirarchy);
			}
			System.Diagnostics.Debug.WriteLine("********** Finished TestAll " + psTestName + "  **************");
		}

		private void TransformStructureToVerilog()
		{
			// danger
			TextFile.WipeDirectory(RapidHardware.Tools.WorkingPath,"*.v");
			// danger
			TopLevelComponent.PrepareVerilogStructure();
			TopLevelComponent.BaseTransformStructureToVerilog();
		}

		public void TransformStructure(StructureTransformType peStructureTransformType)
		{
			switch(peStructureTransformType)
			{
				case StructureTransformType.Verilog: 
					TransformStructureToVerilog();
					break;
			}
		}
	}
}
